﻿using DiffuseEnjoyIdle.Model.Config;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System.Text;

namespace DiffuseEnjoyIdle.MessageCenter.RabbitMQ
{
    public class RabbitMQClient
    {
        private readonly ILogger<RabbitMQClient> _logger;
        private readonly IModel _channel;
        private readonly IDictionary<string, EventHandler<BasicDeliverEventArgs>> _dic;
        private readonly IConnection _connection;

        public RabbitMQClient(IOptions<RabbitMQConfig> options
            , ILogger<RabbitMQClient> logger
            , IEnumerable<IMQHandler> handles)
        {
            var rabbitMqConfig = options.Value;
            _logger = logger;
            _dic = new Dictionary<string, EventHandler<BasicDeliverEventArgs>>();

            foreach (var handle in handles)
            {
                if (_dic.TryAdd(handle.QueueName, async (obj, args) => await handle.ReceivedHandler(obj, args)))
                {
                    _dic[handle.QueueName] += BaseHandler;
                }
            }

            ConnectionFactory factory = new ConnectionFactory
            {
                UserName = rabbitMqConfig.UserName,
                Password = rabbitMqConfig.Password,
                HostName = rabbitMqConfig.HostName,
                Port = rabbitMqConfig.Port,
                VirtualHost = rabbitMqConfig.VirtualHost,

            };


            _connection = factory.CreateConnection();

            _channel = _connection.CreateModel();


        }

        public Task StartAsync()
        {
            foreach (var (key, value) in _dic)
            {
                Register(key, value);
            }

            return Task.CompletedTask;
        }

        public Task StopAsync()
        {
            _channel.Close();
            _connection.Close();

            return Task.CompletedTask;
        }

        private void Register(string queueName, EventHandler<BasicDeliverEventArgs> eventHandler)
        {
            _channel.QueueDeclare(queueName, true, false, false);

            EventingBasicConsumer consumer = new EventingBasicConsumer(_channel);
            consumer.Received += eventHandler;

            _channel.BasicConsume(queueName, false, consumer);

            _logger.LogInformation($"Register Channel:{queueName}");
        }

        private void BaseHandler(object obj, BasicDeliverEventArgs args)
        {
            var message = Encoding.UTF8.GetString(args.Body.ToArray());
            _logger.LogInformation($"收到消息:{message}");
        }
    }
}
